#ifndef xpack_utils_value_holder
#define xpack_utils_value_holder
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::utils_value_holder::inc
#include"define/base_type.hpp"
#include"define/nullref.hpp"
#include"dumb/disable_copy.hpp"
#include"macro/xalign.hpp"
#include"macro/xexport.hpp"
#include"macro/xforward.hpp"
#include"macro/xlikely.hpp"
#include"macro/xnew.hpp"
#include"macro/xstruct.hpp"
#include"memop/copy.hpp"
#include"meta/has_constructor.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_value_holder::origin{
    template<class type_t>
    xstruct(
        xtmpl(value_holder, type_t),
        xpubb(inc::disable_copy),
        xasso(type_t)
    )
    private:
        xalign(alignof(type_t))
        u08 m_value[sizeof(type_t)];
        uxx m_index;

        typedef struct core{
            type_t data;
            core(auto ... list) : data{list...}{}
        } * corep;
    public:
        xprops()
            // 使用于数组元素返回值，包含下标信息，如果无需此参数，
            // 在 value_holder 构造的时候设置成非 no_exist 值即可，或者保持默认值 0
            xpubget(index, uxx);
            xpubgetx(value, type_t &){
                xr{
                    xlikely(xthe.m_index != not_exist){
                        return *(type_t *)xthe.m_value;
                    }
                    return inc::nullref;
                }

                xprops_operator_plus(*(type_t *)xthe.m_value, type_t)
            };

            xpubgetx(is_hold_value, bool){
                xr{
                    return xthe.m_index != not_exist;
                }
            };
        $

        xprops_operator()
    public:
        constexpr value_holder() : m_value{}, m_index(not_exist){}

        template<class forward_type_t>
        requires(inc::has_constructor<type_t, void(forward_type_t &&)>)
        constexpr value_holder(forward_type_t && value, uxx index = 0) : 
            m_value{}, 
            m_index(index){
            xnew(m_value) type_t(xforward(value));
        }

        constexpr value_holder(the_t && self) :
            m_value{}, 
            m_index(self.m_index){

            inc::copy_unsafe(m_value, self.m_value, sizeof(type_t));
            self.m_index    = not_exist;
        }

        ~value_holder(){
            this->discard();
        }

        void discard(){
            if (m_index != not_exist){
                m_index     = not_exist;
                corep(m_value)->~core();
            }
        }

        template<class forward_type_t>
        requires(inc::has_constructor<type_t, void(forward_type_t &&)>)
        void hold(forward_type_t && value){
            if (m_index != not_exist){
                *((type_t *)m_value) = xforward(value);
            }
            else{
                xnew(this) the_t(xforward(value));
            }
        }

        the_t & operator=(type_t const &) = delete;

        the_t & operator=(the_t && value){
            xlikely(& value != this){
                this->discard();
                xnew(this) the_t((the_t &&)value);
                return xthe;
            }
            else{
                return xthe;
            }
        }

        the_t && hand_over() {
            return (the_t &&)xthe;
        }
    $
}

#endif

xexport_space(mixc::utils_value_holder::origin)
